﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Web.HttpUtility;
using System.IO;

namespace WebGetter
{
    public partial class WinForm : Form
    {
        PageRepository respository = new PageRepository();

        public WinForm()
        {
            InitializeComponent();
            string url = ReadUrl();
            if (string.IsNullOrEmpty(url))
                url = @"http://tieba.baidu.com/f?kz=1069943671";
            txtUrl.Text = url;
        }

        Page currPage = null;
        List<Page> pages = new List<Page>();
        BackgroundWorker worker = new BackgroundWorker();

        private void button1_Click(object sender, EventArgs e)
        {
            pages = new List<Page>();
            string url = txtUrl.Text;
            Page page = GetPage(url);
            if (page == null)
            {
                ReportDownloadError(url);
                return;
            }
            pages.Add(page);
            BindPage(page);
            if (worker != null && worker.IsBusy)
            {
                worker.CancelAsync();
            }
            worker = new BackgroundWorker();
            worker.WorkerSupportsCancellation = true;
            this.button1.Enabled = false;
            worker.DoWork += (s, args) => GetNextPage(page, args);
            worker.WorkerReportsProgress = true;
            worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
            worker.RunWorkerAsync();
            worker.RunWorkerCompleted -= (s, args) => RebindData();
        }

        private static void ReportDownloadError(string url)
        {
            MessageBox.Show(string.Format("下载页面{0}失败，请查看日志文件获取详细信息", url), "下载失败");
            return;
        }

        void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            RebindData();
            statusStrip1.Text = e.ProgressPercentage.ToString();
        }


        private void BindPage(Page page)
        {
            if (page == null)
            {
                MessageBox.Show("不存在的页");
                return;
            }
            if (page == currPage)
                return;

            currPage = page;
            this.Text = page.Title;
            txtUrl.Text = page.Url.ToString();
            Func<Reply, bool> func = null;
            if (checkBox1.Checked)
            {
                func = r => r.Author == page.Author;
            }
            webBrowser1.DocumentText = new PageRender(page).GetContent(func);
            SaveUrl(page.Url);
        }

        private void RebindData()
        {
            lbPages.DataSource = null;
            lbPages.DataSource = pages;
            lbPages.DisplayMember = Keys.PageNo;
        }

        private void GetNextPage(Page page, DoWorkEventArgs args)
        {
            var downloadSuccess = true;
            while (!string.IsNullOrEmpty(page.NextPageUrl))
            {
                if (worker.CancellationPending)
                {
                    downloadSuccess = false;
                    MessageBox.Show("DownLoad Canceled...");
                    break;
                }
                string url = page.NextPageUrl.ToString();
                page = GetPage(url);
                if (page == null)
                {
                    ReportDownloadError(url);
                    downloadSuccess = false;
                    break;
                }
                pages.Add(page);
                worker.ReportProgress(page.PageNo / page.TotalNo);
            }
            this.button1.Invoke(new MethodInvoker(() => button1.Enabled = true));
            if (downloadSuccess)
                MessageBox.Show("DownLoad Finished...");
            RebindData();
        }

        private static Page GetPage(string url)
        {
            int MAX_TRY_COUNT = 3;
            int i = 0;
            while (i < MAX_TRY_COUNT)
            {
                try
                {
                    return Page.GetPage(url);
                }
                catch (Exception ex)
                {
                    Logger.Current.Log(string.Format("{0}\t try {1} time fault.detals:", DateTime.Now, i + 1));
                    Logger.Current.Log(ex.ToString());
                }
            }

            Logger.Current.Log(string.Format("request {0} fault", url));
            return null;
        }

        private string ReadUrl()
        {
            string url = string.Empty;
            using (FileStream fs = new FileStream(@"lasturl", FileMode.OpenOrCreate))
            {
                byte[] bytes = new byte[fs.Length];
                fs.Read(bytes, 0, (int)fs.Length);
                url = Encoding.UTF8.GetString(bytes);
            }
            return url;
        }

        private void SaveUrl(string url)
        {
            using (FileStream fs = new FileStream(@"lasturl", FileMode.Create))
            {
                byte[] bytes = Encoding.UTF8.GetBytes(url);
                fs.Write(bytes, 0, bytes.Length);
            }
        }

        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            BindCurrPage();
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            BindCurrPage();
        }

        private void BindCurrPage()
        {
            int selectedIndex = lbPages.SelectedIndex;
            if (selectedIndex < 0)
                return;
            Page page = pages[selectedIndex];
            if (page == null)
            {
                return;
            }
            BindPage(page);
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            //foreach (var page in pages)
            //{
            //    respository.Save(page);
            //}
            var all = respository.GetAll();
            int count = all.Count();
            lbPages.DataSource = all;
        }

        private void btnLoadTemplate_Click(object sender, EventArgs e)
        {
            PageRender.ReloadTemplate();
            BindCurrPage();
        }
    }
}
